home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 October / EnigmA AMIGA RUN 01 (1995)(G.R. Edizioni)(IT)[!][issue 1995-10][Aminet 7].iso / Aminet / dev / gcc / GccFindHit.lha / GccFindHit.c < prev    next >
C/C++ Source or Header  |  1995-05-22  |  6KB  |  259 lines

  1. /* GccFindHit V1.0, 22/05/95
  2. *
  3. *  The same than FindHit by Michael Sinz, but for GCC users
  4. *  Usage: FindHit <executable file> <list of offsets in hexadecimal>
  5. *  The file should have been linked with the '-g' flag passed to gcc
  6. *  to turn on debugging information (the 'stabs')
  7. *
  8. *  FindHit outputs the line numbers matching with the offsets given by
  9. *  Enforcer (or whatever). Currently, there is no need
  10. *  to provide the hunk number because it should always be zero.
  11. *
  12. *  Copyright (C) 1995 Daniel Verite -- daniel@brasil.frmug.fr.net
  13. *  This program is distributed under the General GNU Public License version 2
  14. *  See the file COPYING for information about the GPL
  15. *
  16. */
  17.  
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <fcntl.h>
  21. #include <unistd.h>
  22. #include <string.h>
  23.  
  24. #include "defs.h"
  25.  
  26. extern int errno;
  27.  
  28. int ExeFile,NbOffs;
  29. unsigned long *SearchOffs;
  30.  
  31. int Read4 (long *buf)
  32. {
  33.   if (read (ExeFile,buf,4)==4) {
  34.     *buf = GETLONG(*buf);
  35.     return 1;
  36.   }
  37.   else
  38.     return 0;
  39. }
  40.  
  41. struct Header *ReadHeader ()
  42. {
  43.   long nb,size;
  44.   struct Header *h;
  45.   int i;
  46.  
  47.   /* skip hunk names */
  48.   while (Read4 (&size) && size)
  49.     lseek (ExeFile, size<<2, SEEK_CUR);
  50.  
  51.   /* reads the number of hunks */
  52.   if (!Read4(&nb))
  53.     return NULL;
  54.   h = (struct Header*)malloc(sizeof(struct Header)+(nb-1)*sizeof(long));
  55.   if (!h)
  56.     return NULL;
  57.   h->nb_hunks = nb;
  58.   if (Read4 (&h->first) && Read4 (&h->last)) {
  59.     for (i=0; i<nb; i++)
  60.       if (!Read4 (&h->sizes[i])) {
  61.     free (h);
  62.     return NULL;
  63.       }
  64.   }
  65.   return h;
  66. } /* ReadHeader() */
  67.  
  68. int long_cmp (long *e1,long *e2)
  69. {
  70.   return (*e1)<(*e2);
  71. } /* long_cmp() */
  72.  
  73. void SkipRelocation ()
  74. {
  75.   unsigned long no; /* number of offsets */
  76.   long h;  /* hunk number */
  77.   while (Read4 (&no) && no && Read4 (&h))
  78.     lseek (ExeFile, no<<2, SEEK_CUR);
  79. }
  80.  
  81. /* this function hasn't been tested; AFAIK, ld won't output short relocs,
  82.    so it's useless for now */
  83. void SkipShortRel ()
  84. {
  85.   unsigned long no;
  86.   short h;
  87.   while (Read4 (&no) && no && read (ExeFile, &h, sizeof h))
  88.     lseek (ExeFile, no<<1, SEEK_CUR);
  89. }
  90.  
  91. /* can be slow if I/O buffering doesn't do some read-ahead */
  92. void SkipSymbols ()
  93. {
  94.   long nl; /* name length in long words */
  95.   while (Read4 (&nl) && nl) {
  96.     /* skips the name + the value */
  97.     lseek (ExeFile, (nl+1)<<2, SEEK_CUR);
  98.   }
  99. }
  100.  
  101. void GetLines (long symsz, BSD_SYM *syms, long strsz, char *strings)
  102. {
  103.   long nbsyms = symsz/sizeof(BSD_SYM);
  104.   BSD_SYM *sym = syms;
  105.   unsigned char prev_type;
  106.   char *srcname="",*prev_src=srcname;
  107.   unsigned short prev_line=0;
  108.   unsigned long offs,prev_offs=-1UL;
  109.   int i;
  110.  
  111.   while (nbsyms--) {
  112.     switch (sym->type) {
  113.     case N_SO:
  114.     case N_SOL:
  115.       srcname = strings + GETLONG (sym->strx);
  116.       break;
  117.     case N_SLINE:
  118.       offs = OFFSET_N_SLINE (GETLONG (sym->value));
  119.       for (i=0; i<NbOffs; i++) {
  120.     if (SearchOffs[i]>=prev_offs && SearchOffs[i]<offs) {
  121.       printf ("%s: line %hd, offset 0x%lx\n", prev_src, prev_line,
  122.           prev_offs);
  123.     }
  124.       }
  125.       prev_offs = offs;
  126.       prev_line = GETWORD (sym->desc);
  127.       prev_src = srcname;
  128.       break;
  129.     }
  130.     prev_type = sym->type;
  131.     sym++;
  132.   }
  133.   /* the last SLINE is a special case */
  134.   for (i=0; i<NbOffs; i++) {
  135.     if (SearchOffs[i]==prev_offs) {
  136.       printf ("%s: line %hd, offset 0x%lx\n", prev_src, prev_line,
  137.           prev_offs);
  138.     }
  139.   }
  140. }
  141.  
  142. void HunkDebug ()
  143. {
  144.   long hunksz, symsz, strsz;
  145.   struct bsd_header hdr;
  146.   long pos = lseek (ExeFile, 0, SEEK_CUR);
  147.   char *strings,*syms;
  148.  
  149.   if (pos<0)
  150.     return;
  151.   if (Read4(&hunksz) && read (ExeFile, &hdr, sizeof(hdr)) == sizeof(hdr)) {
  152.     if (GETLONG(hdr.magic)==ZMAGIC) {
  153.       /* seems to be gcc-compiled */
  154.       strsz = GETLONG (hdr.strsz);
  155.       symsz = GETLONG (hdr.symsz);
  156.       if (strsz+symsz != 0) {
  157.     syms = (char*)malloc (symsz);
  158.     strings = (char*)malloc (strsz);
  159.     if (strings && syms) {
  160.       if (read (ExeFile, syms, symsz)==symsz &&
  161.           read (ExeFile, strings, strsz)==strsz) {
  162.         GetLines (symsz, (BSD_SYM*)syms, strsz, strings);
  163.       }
  164.       free (strings); free (syms);
  165.     }
  166.       }
  167.     }
  168.   }
  169.   /* go to the end of the hunk whatever happened before */
  170.   lseek (ExeFile, pos+((hunksz+1)<<2), SEEK_SET);
  171. }
  172.  
  173. void DoHunks (struct Header *h)
  174. {
  175.   long hnum,size,nsec=0;
  176.   while (Read4 (&hnum)) {
  177.     switch (hnum) {
  178.     case HUNK_CODE:
  179.     case HUNK_DATA:
  180.       if (Read4 (&size)) {
  181.     nsec++;
  182.     lseek (ExeFile, (size&0x3fffffff)<<2, SEEK_CUR);
  183.       }
  184.       break;
  185.     case HUNK_BSS:
  186.       nsec++;
  187.       Read4 (&size);
  188.     case HUNK_END:
  189.     case HUNK_BREAK:
  190.       break;
  191.     case HUNK_RELOC32:
  192.     case HUNK_RELOC16:
  193.     case HUNK_RELOC8:
  194.     case HUNK_DRELOC32:
  195.     case HUNK_DRELOC16:
  196.     case HUNK_DRELOC8:
  197.       SkipRelocation();
  198.       break;
  199.     case HUNK_RELOC32SHORT:
  200.       SkipShortRel ();
  201.       break;
  202.     case HUNK_SYMBOL:
  203.       SkipSymbols();
  204.       break;
  205.     case HUNK_DEBUG: /* here we are... */
  206.       HunkDebug ();
  207.       break;
  208.     default:
  209.       fprintf (stderr, "Unexpected hunk 0x%lx\n", hnum);
  210.       return;
  211.     }
  212.   }
  213. } /* DoHunks() */
  214.  
  215. void Out(int code)
  216. {
  217.   if (ExeFile>0) close (ExeFile);
  218.   if (SearchOffs) free (SearchOffs);
  219.   exit (code);
  220. }
  221.  
  222. int main(int argc,char **argv)
  223. {
  224.   long HunkNum;
  225.   struct Header *header=NULL;
  226.   int i;
  227.  
  228.   if (argc<3) {
  229.     fprintf (stderr,"Usage: %s <file> <hex offsets>\n",argv[0]);
  230.     Out (1);
  231.   }
  232.   ExeFile = open (argv[1], O_RDONLY);
  233.   if (ExeFile<0) {
  234.     fprintf (stderr,"can't open %s:%s\n", argv[1], strerror (errno));
  235.     Out (1);
  236.   }
  237.   NbOffs = argc-2;
  238.   SearchOffs = (long*)malloc (sizeof (long)*NbOffs);
  239.   if (!SearchOffs) {
  240.     fprintf (stderr,"No memory\n");
  241.     Out (1);
  242.   }
  243.   for (i=0; i<NbOffs; i++) {
  244.     if (sscanf (argv[i+2],"%lx",&SearchOffs[i])!=1) {
  245.       fprintf (stderr, "Operand %s is not an hex offset\n", argv[i+2]);
  246.       Out (1);
  247.     }
  248.   }
  249.   if (!Read4(&HunkNum) || HunkNum!=HUNK_HEADER || !(header=ReadHeader())) {
  250.     fprintf (stderr, "%s is not an amigados executable\n", argv[1]);
  251.     Out (1);
  252.   }
  253.   DoHunks (header);
  254.   free (header);
  255.   Out (0);
  256.   return 0; /* another brick in the -Wall */
  257. } /* main() */
  258.  
  259.